import io, re
import Global

flag_l = 0
tokensPath = './Tokens.txt'

def insertToQueue(s1, s2, s3):
    Global.lexical_queue.append(s1)
    Global.symbol_queue.append(s2)
    Global.semantics_queue.append(s3)

def importTokens():
    tokensFile = file(tokensPath, 'r')
    i = 1
    for line in tokensFile:
        Global.tokens[line.split().pop()] = i
        i += 1
    tokensFile.close()

def delete(regular, line): #remove the string which match the regular expression from the line
    s = re.compile(regular).match(line).group()
    return line.replace(s, '', 1)

def match(regular1, line, regular2, token): #use to match integer, real, identifier and string
    s = re.compile(regular1).match(line).group()
    s1 = ''
    if re.compile(regular2).match(s) != None:
        s = re.compile(regular2).match(s).group()
        s1 = 8*'	'+'Token: '+s+' Code: '+str(Global.tokens[token])+'\n'
        insertToQueue(Global.tokens[token], s, s)
    else:
        s1 = 8*'	'+'Invalid '+token+': '+s+'\n'
    if Global.flag[2] == 1:
        Global.outputFile.write(s1)
    return line.replace(s, '', 1)

def matchReserve(regular1, line): #use to match reserve words
    s = re.compile(regular1).match(line).group()
    s1 = ''
    if s in Global.tokens:
        s1 = 8*'	'+'Token: '+s+' Code: '+str(Global.tokens[s])+'\n'
        insertToQueue(Global.tokens[s], s, '#')
    else:
        s1 = 8*'	'+'Invalid reserve word: '+s+'\n'
    if Global.flag[2] == 1:
        Global.outputFile.write(s1)
    return line.replace(s, '', 1)

def matchPunctuation(regular0, line, regular1, regular2): #use to match mutiple and single ASCII characters
    s = re.compile(regular0).match(line).group()
    s1 = ''
    if re.compile(regular1).match(s) != None:
        s = re.compile(regular1).match(s).group()
        if s in Global.tokens:
            s1 = 8*'	'+'Token: '+s+' Code: '+str(Global.tokens[s])+'\n'
            insertToQueue(Global.tokens[s], s, '#')
            if Global.flag[2] == 1:
                Global.outputFile.write(s1)
            return line.replace(s, '', 1)

    if re.compile(regular2).match(s) != None:
        s = re.compile(regular2).match(s).group()
        if s in Global.tokens:
            s1 = 8*'	'+'Token: '+s+' Code: '+str(Global.tokens[s])+'\n'
            insertToQueue(Global.tokens[s], s, '#')
            if Global.flag[2] == 1:
                Global.outputFile.write(s1)
            return line.replace(s, '', 1)
    s1 = 8*'	'+'Invalid ASCII Character: '+s+' ASCII value is '+str(ord(s))+'\n'
    if Global.flag[2] == 1:
        Global.outputFile.write(s1)
    return line.replace(s, '', 1)

def MatchFlags(regular, line):
    s = re.compile(regular).match(line).group()
    for i in range(len(Global.flag)):
        if re.compile('.*\+'+str(i)+'\D.*').match(s) != None:
            Global.flag[i] = 1
        elif re.compile('.*-'+str(i)+'\D.*').match(s) != None:
            Global.flag[i] = 0
        else:
            pass
    return  line.replace(s, '', 1)

def lexical(line):
    global flag_l
    importTokens()
    while line != '':
        if flag_l == 1:
            if re.compile('.*?\*/').match(line) != None: #match comment ...*/
                line = delete('.*?\*/', line)
                flag_l = 0
                continue
            else:
                break
        else:
            if re.compile('##.*?##').match(line) != None: #match flags
                line =  MatchFlags('##.*?##',line)
            elif re.compile('/\*.*').match(line) != None: #match comment /*...
                s = re.compile('/\*.*').match(line).group()
                if re.compile('/\*.*?\*/').match(s) != None: #match comment /*...*/
                    line = delete('/\*.*?\*/', line)
                    continue
                else:
                    flag_l = 1
            elif re.compile('\s+').match(line) != None: #match space
                line = delete('\s+', line)

            elif re.compile('//.*').match(line) != None: #match comment //...
                line = delete('//.*', line)

            elif re.compile('-?\d+\.\d+').match(line) != None: #match real
                line = match('-?\d+\.\d+', line, '^-?([1-9](\d{5}\.\d|\d{4}\.\d{1,2}|\d{3}\.\d{1,3}|\d{2}\.\d{1,4}|\d\.\d{1,5})|0\.\d{1,6})$', 'real')

            elif re.compile('-?\d+').match(line) != None: #match integer
                line = match('-?\d+', line, '^-?[1-9]\d{0,8}$|^0$', 'integer')

            elif re.compile('".*').match(line) != None: #match string
                line = match('".*', line, '"[^"]*"', 'string')

            elif re.compile('[a-z]\w*').match(line) != None: #match identifier
                line = match('[a-z]\w*', line, '^[a-z]\w{0,15}$', 'var')

            elif re.compile('[A-Z]+').match(line) != None: #match reserve word
                line = matchReserve('[A-Z]+', line)

            elif re.compile('..?').match(line) != None:  #match ASCII characters
                line = matchPunctuation('..?', line, '..', '.')

            else:
                Global.outputFile.write(8*'	'+'Unknown Error')
